package org.budo.dubbo.protocol.http.page;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.budo.dubbo.protocol.http.page.entity.FunctionEntity;
import org.budo.dubbo.protocol.http.page.util.InterfaceStructureUtil;
import org.budo.dubbo.protocol.http.util.BudoReflectionUtil;
import org.budo.support.lang.util.IoUtil;
import org.budo.support.lang.util.ReflectUtil;
import org.budo.support.spring.io.util.ResourceUtil;

import com.alibaba.dubbo.common.utils.CollectionUtils;

/**
 * @author lmw
 */
public class InterfacePage extends AbstractPage {
    private static final long serialVersionUID = 7663524524701486779L;

    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String interfaceNameInUrl = request.getParameter("interface");
        this.renderInterfacePage(request, response, interfaceNameInUrl);
    }

    private void renderInterfacePage(HttpServletRequest request, HttpServletResponse response, String interfaceNameInUrl) throws IOException {
        String matchedInterfaceName = BudoReflectionUtil.getMatchedInterfaceNameCached(interfaceNameInUrl); // 已缓存

        Map<String, Object> controllerMap = InterfaceStructureUtil.controllerMapByType(interfaceNameInUrl);
        if (null == matchedInterfaceName && null != controllerMap) {
            this.renderControllerPage(controllerMap, request, response);
            return;
        }

        if (null == matchedInterfaceName) {
            String errorResponse = "<h1>error:" + " type " + interfaceNameInUrl + " not found" + "</h1>" //
                    + "<a href=\"?from=type-not-found&type=" + interfaceNameInUrl + "\">Back To Index</a>";
            IoUtil.write(new ByteArrayInputStream(errorResponse.getBytes()), response.getOutputStream());
            return;
        }

        Class interfaceType = ReflectUtil.classForName(matchedInterfaceName);
        List<Map<String, Object>> functionMapList = InterfaceStructureUtil.interfaceFunctions(interfaceType);

        Map<String, Object> dataMap = CollectionUtils.toMap("functions", functionMapList, //
                "interface", InterfaceStructureUtil.interfaceMapByType(matchedInterfaceName));

        String templateInput = ResourceUtil.classPathResourceInputStreamToString("api-doc-template/interface.htm");
        this.renderPage(templateInput, dataMap, request, response);
    }

    private void renderControllerPage(Map<String, Object> map, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String typeName = map.get("fullName").toString();
        Class interfaceType = ReflectUtil.classForName(typeName);

        List<FunctionEntity> functionMapList = InterfaceStructureUtil.requestMappingFunctions(interfaceType);
        Map<String, Object> dataMap = CollectionUtils.toMap("functions", functionMapList, //
                "interface", InterfaceStructureUtil.interfaceMapByType(typeName));

        String templateInput = ResourceUtil.classPathResourceInputStreamToString("api-doc-template/interface.htm");
        this.renderPage(templateInput, dataMap, request, response);
    }
}